home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’87 / Source ƒ.sit / Source ƒ / C ƒ / TRANS-LSC / MSkelRgn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-04  |  4.4 KB  |  213 lines  |  [TEXT/KAHL]

  1. /*
  2.     TransSkel multiple-window demonstration: Region module
  3.  
  4.     This module handles a window in which the mouse may be clicked and
  5.     dragged to draw rectangles.  The rects so drawn are combined into
  6.     a single region, the outline of which is drawn.  Rects drawn while
  7.     the shift key is held down are subtracted from the region.
  8.     Double-clicking the mouse clears the display.  If the window is
  9.     resized, the region that is drawn is resized as well.
  10.  
  11.     14 June 1986        Paul DuBois
  12.  
  13.     Changes:
  14.     07/08/86 Changed outline so that it's drawn as a marquee.
  15. */
  16.  
  17. # include    "MultiSkel.h"
  18.  
  19.  
  20. WindowPtr    rgnWind;
  21. Rect        rgnPortRect;    /* portRect size - for detecting wind grows */
  22. RgnHandle    selectRgn;        /* current region to be drawn */
  23. long        selectWhen;        /* time of last click */
  24. Point        selectWhere;    /* location of last click */
  25.  
  26. Pattern        marqueePat = { 0x0f, 0x87, 0xc3, 0xe1, 0xf0, 0x78, 0x3c, 0x1e };
  27.  
  28.  
  29. static Clobber ()
  30. {
  31.     DisposeRgn (selectRgn);
  32.     CloseWindow (rgnWind);
  33. }
  34.  
  35.  
  36. /*
  37.     On double-click, clear window.  On single click, draw gray selection
  38.     rectangle as long as mouse is held down.  If user draws non-empty rect,
  39.     then add it to the selection region and redraw the region's outline.
  40.     If the shift-key was down, then subtract the selection region instead
  41.     and redraw.
  42. */
  43.  
  44.  
  45. static Mouse (thePt, t, mods)
  46. Point    thePt;
  47. long    t;
  48. int        mods;
  49.  
  50. {
  51. Rect        r;
  52. RgnHandle    rgn;
  53.  
  54.     r = rgnWind->portRect;
  55.     if (thePt.h >= r.right - 15)        /* must not click in right edge */
  56.         return;
  57.     if (t - selectWhen <= GetDblTime ())    /* it's a double-click */
  58.     {
  59.         selectWhen = 0L;        /* don't take next click as dbl-click */
  60.         SetWindClip (rgnWind);
  61.         EraseRgn (selectRgn);
  62.         ResetWindClip ();
  63.         SetEmptyRgn (selectRgn);    /* clear region */
  64.     }
  65.     else
  66.     {
  67.         selectWhen = t;                /* update click variables */
  68.         selectWhere = thePt;
  69.         DoSelectRect (thePt, &r);    /* draw selection rectangle */
  70.         if (!EmptyRect (&r))
  71.         {
  72.             EraseRgn (selectRgn);
  73.             selectWhen = 0L;
  74.             rgn = NewRgn ();
  75.             RectRgn (rgn, &r);
  76.             if ((mods & shiftKey) != 0)        /* test shift key */
  77.                 DiffRgn (selectRgn, rgn, selectRgn);
  78.             else
  79.                 UnionRgn (selectRgn, rgn, selectRgn);
  80.             DisposeRgn (rgn);
  81.         }
  82.     }
  83. }
  84.  
  85.  
  86. /*
  87.     Redraw the current region.  If the window was resized, resize
  88.     the region to fit.
  89. */
  90.  
  91. static Update (resized)
  92. Boolean    resized;
  93. {
  94. Rect    r;
  95.  
  96.     EraseRect (&rgnWind->portRect);
  97.     if (resized)
  98.     {
  99.         r = rgnWind->portRect;
  100.         rgnPortRect.right -= 15;    /* don't use right edge of window */
  101.         r.right -= 15;
  102.         MapRgn (selectRgn, &rgnPortRect, &r);
  103.         rgnPortRect = rgnWind->portRect;
  104.     }
  105.     DrawGrowBox (rgnWind);
  106.     Idle ();
  107. }
  108.  
  109.  
  110. static Activate (active)
  111. Boolean    active;
  112. {
  113.     DrawGrowBox (rgnWind);
  114.     if (active)
  115.         DisableItem (editMenu, 0);
  116.     else
  117.         EnableItem (editMenu, 0);
  118.     DrawMenuBar ();
  119. }
  120.  
  121.  
  122. MarqueeRgn (r)
  123. RgnHandle    r;
  124. {
  125. PenState    p;
  126. Byte        b;
  127. int            i;
  128.  
  129.     GetPenState (&p);
  130.     PenPat (marqueePat);
  131.     PenMode (patCopy);
  132.     FrameRgn (r);
  133.     SetPenState (&p);
  134.     b = marqueePat[0];        /* shift pattern for next call */
  135.     for (i = 0; i < 7; ++i)
  136.         marqueePat[i] = marqueePat[i+1];
  137.     marqueePat[7] = b;
  138. }
  139.  
  140.  
  141. static Idle ()
  142. {
  143. int        i;
  144.  
  145.     SetWindClip (rgnWind);
  146.     MarqueeRgn (selectRgn);    /* draw selection region outline */
  147.     ResetWindClip ();        /* restore previous clipping */
  148. }
  149.  
  150. /*
  151.     While mouse is down, draw gray selection rectangle in the current
  152.     port.  Return the resultant rect in dstRect.  The rect is always
  153.     clipped to the current portRect.
  154. */
  155.  
  156. DoSelectRect (startPoint, dstRect)
  157. Point    startPoint;
  158. Rect    *dstRect;
  159. {
  160. Point        pt, dragPt;
  161. Rect        rClip;
  162. GrafPtr        thePort;
  163. Boolean        result;
  164. PenState    ps;
  165. int            i;
  166.  
  167.     GetPort (&thePort);
  168.     rClip = thePort->portRect;
  169.     rClip.right -= 15;
  170.     GetPenState (&ps);
  171.     PenPat (gray);
  172.     PenMode (patXor);
  173.     dragPt = startPoint;
  174.     Pt2Rect (dragPt, dragPt, dstRect);
  175.     FrameRect (dstRect);
  176.     for (;;)
  177.     {
  178.         GetMouse (&pt);
  179.         if (!EqualPt (pt, dragPt))    /* mouse has moved, change region */
  180.         {
  181.             FrameRect (dstRect);
  182.             dragPt = pt;
  183.             Pt2Rect (dragPt, startPoint, dstRect);
  184.             result = SectRect (dstRect, &rClip, dstRect);
  185.             FrameRect (dstRect);
  186.             for (i = 0; i < 1000; ++i) { /* empty */ }
  187.         }
  188.         if (!StillDown ()) break;
  189.     }
  190.     FrameRect (dstRect);    /* erase last rect */
  191.     SetPenState (&ps);
  192. }
  193.  
  194.  
  195.  
  196. RgnWindInit ()
  197. {
  198.     rgnWind = GetNewWindow (rgnWindRes, nil, -1L);
  199.     SkelWindow (rgnWind,
  200.                 Mouse,        /* draw rectangles */
  201.                 nil,        /* ignore keyclicks */
  202.                 Update,
  203.                 Activate,
  204.                 nil,        /* no close proc */
  205.                 Clobber,    /* disposal proc */
  206.                 Idle,        /* idle proc */
  207.                 true);
  208.  
  209.     rgnPortRect = rgnWind->portRect;
  210.     selectRgn = NewRgn ();    /* selected region empty initially */
  211.     selectWhen = 0L;        /* first click can't be taken as dbl-click */
  212. }
  213.